﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RoketPack.Management;
using System.Xml;
using Microsoft.Win32;
using System.Security;
using RoketPack.IM;

namespace RoketPack
{
    public partial class SettingsForm : Form
    {
        private Manager m_Manager;
        private bool m_IsLoaded = false;

        private AccountSettings m_IMAccountSettings = null;
        private NotificationSettings m_IMNotificationSettings = null;

        internal SettingsForm(Manager manager)
        {
            InitializeComponent();

            // Set the manager variable.
            this.m_Manager = manager;

            // Expand all of the nodes in the settings tree view.
            this.c_SettingsTreeView.ExpandAll();

            // Hide the tabs.
            this.c_TabHidingPanel.BringToFront();

            // Load the repository configuration.
            LoadRepositoryConfiguration();

            // Load the basic settings.
            LoadBasicSettingsConfiguration();

            // Load the IM account details configuration.
            LoadIMAccountConfiguration();

            this.m_IsLoaded = true;
        }

        #region Configuration Loading
        /// <summary>
        /// Loads the basic settings for the settings page.
        /// </summary>
        private void LoadBasicSettingsConfiguration()
        {
            // Set the Run At Startup checkbox to checked depending on whether
            // the computer is configured to run RoketPack.
            try
            {
                RegistryKey reg = Registry.CurrentUser;
                RegistryKey key = reg.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                if (key.GetValue("RoketPack") == null)
                    this.c_RunAtStartupCheckBox.Checked = false;
                else if ((string)key.GetValue("RoketPack") != UNC.UniversalApplicationPath)
                {
                    this.c_RunAtStartupCheckBox.Checked = false;
                    key.DeleteValue("RoketPack");
                }
                else
                    this.c_RunAtStartupCheckBox.Checked = true;
            }
            catch (SecurityException)
            {
                // Not running as administrator.
                RegistryKey reg = Registry.CurrentUser;
                RegistryKey key = reg.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run", false);
                if (key.GetValue("RoketPack") == null)
                    this.c_RunAtStartupCheckBox.Checked = false;
                else if ((string)key.GetValue("RoketPack") != UNC.UniversalApplicationPath)
                {
                    this.c_RunAtStartupCheckBox.Checked = false;
                    key.DeleteValue("RoketPack");
                }
                else
                    this.c_RunAtStartupCheckBox.Checked = true;

                // The user can't change this because they aren't administrator.
                this.c_RunAtStartupCheckBox.Enabled = false;
            }
        }

        /// <summary>
        /// Loads the configuration of the repositories for the settings
        /// page.
        /// </summary>
        private void LoadRepositoryConfiguration()
        {
            // We need to copy the contents of the Manager's list, not copy
            // the list itself.  That way we can discard changes if the user
            // presses cancel.
            this.c_RepositoryManager.Repositories = new List<Repository>();
            foreach (Repository r in this.m_Manager.Repositories)
                this.c_RepositoryManager.Repositories.Add(r);
        }

        /// <summary>
        /// Loads the configuration of the IM account details and notifications.
        /// </summary>
        private void LoadIMAccountConfiguration()
        {
            // Load account information
            this.m_IMAccountSettings = new AccountSettings();
            this.m_IMAccountSettings.Username = this.m_Manager.Settings.IMUsername;
            this.m_IMAccountSettings.Password = this.m_Manager.Settings.IMPassword;
            this.c_AccountProperties.SelectedObject = this.m_IMAccountSettings;

            // Load notification information
            this.m_IMNotificationSettings = new NotificationSettings();
            // TODO: Load settings
            this.c_NotificationsProperties.SelectedObject = this.m_IMNotificationSettings;
        }
        #endregion

        /// <summary>
        /// Called when the Cancel button is pressed.  We discard all of our
        /// changes.
        /// </summary>
        private void c_CancelButton_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        /// <summary>
        /// Called when the OK button is pressed.  We write out a new Repositories.xml
        /// document and then get the Manager to reinitialize it's list of repositories.
        /// </summary>
        private void c_OKButton_Click(object sender, EventArgs e)
        {
            // Write the global settings back to disk.
            this.m_Manager.Settings.IMUsername = this.m_IMAccountSettings.Username;
            this.m_Manager.Settings.IMPassword = this.m_IMAccountSettings.Password;
            this.m_Manager.Settings.IMNotifications.OnContactSignIn = this.m_IMNotificationSettings.OnContactSignIn;
            this.m_Manager.Settings.IMNotifications.OnContactStartGame = this.m_IMNotificationSettings.OnContactStartGame;
            this.m_Manager.Settings.IMNotifications.OnContactJoinServer = this.m_IMNotificationSettings.OnContactJoinServer;
            this.m_Manager.Settings.IMNotifications.OnUserStartGame = this.m_IMNotificationSettings.OnUserStartGame;
            this.m_Manager.Settings.IMNotifications.OnUserJoinServer = this.m_IMNotificationSettings.OnUserJoinServer;
            this.m_Manager.Settings.Save();

            // Restart the IM system.
            this.m_Manager.IMManager.Reconnect();

            // Write the repository information back to disk.
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            using (XmlWriter writer = XmlWriter.Create("Repositories.xml", settings))
            {
                writer.WriteStartElement("repositories");

                foreach (Repository r in this.c_RepositoryManager.Repositories)
                {
                    writer.WriteStartElement("repo");
                    writer.WriteAttributeString("url", r.Url);
                    writer.WriteStartElement("name");
                    writer.WriteString(r.Name);
                    writer.WriteEndElement();
                    writer.WriteStartElement("description");
                    writer.WriteString(r.Description);
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
                writer.Close();
            }

            // Get the manager to reload it's list of repositories.
            this.m_Manager.ReinitalizeRepositories();

            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void c_RunAtStartupCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (!this.m_IsLoaded)
                return;

            RegistryKey reg = Registry.CurrentUser;
            RegistryKey key = reg.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run", true);
            if (this.c_RunAtStartupCheckBox.Checked)
                key.SetValue("RoketPack", UNC.UniversalApplicationPath);
            else
                key.DeleteValue("RoketPack");
        }

        private void c_SettingsTreeView_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            // Prevent collapsing of nodes.
            e.Cancel = true;
        }

        private void c_SettingsTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            switch (e.Node.Name)
            {
                case "General":
                case "General_Basic":
                    this.c_TabControl.SelectedIndex = 0;
                    break;
                case "General_Repositories":
                    this.c_TabControl.SelectedIndex = 1;
                    break;
                case "IM":
                case "IM_Account":
                    this.c_TabControl.SelectedIndex = 2;
                    break;
                case "IM_Notifications":
                    this.c_TabControl.SelectedIndex = 3;
                    break;
            }
        }
    }
}
